﻿using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System.Reflection;
using System.Text.Json;
using JsonSerializer = System.Text.Json.JsonSerializer;

namespace SwaggerDoc.Api
{
    #region Newtonsoft

    public class NullToDefaultResolver : DefaultContractResolver
    {
        protected override IList<Newtonsoft.Json.Serialization.JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
        {
            return type.GetProperties()
                .Select(p =>
                {
                    var jp = base.CreateProperty(p, memberSerialization);
                    jp.ValueProvider = new NullToDefaultValueProvider(p);
                    return jp;
                }).ToList();
        }
    }
    public class NullToDefaultValueProvider : Newtonsoft.Json.Serialization.IValueProvider
    {
        private PropertyInfo _MemberInfo;
        public NullToDefaultValueProvider(PropertyInfo memberInfo)
        {
            _MemberInfo = memberInfo;
        }
        public object GetValue(object target)
        {
            object result = _MemberInfo.GetValue(target);
            if (_MemberInfo.PropertyType == typeof(string) && result == null)
            {
                result = "";
            }
            else if (_MemberInfo.PropertyType == typeof(String[]) && result == null)
            {
                result = new string[] { };
            }
            else if (_MemberInfo.PropertyType == typeof(Nullable<Int32>) && result == null)
            {
                result = 0;
            }
            else if (_MemberInfo.PropertyType == typeof(Nullable<long>) && result == null)
            {
                result = 0L;
            }
            else if (_MemberInfo.PropertyType == typeof(Nullable<Decimal>) && result == null)
            {
                result = 0.00M;
            }
            else if (_MemberInfo.PropertyType == typeof(Nullable<DateTime>) && result == null)
            {
                result = null;
            }
            return result;
        }
        public void SetValue(object target, object value)
        {
            _MemberInfo.SetValue(target, value);
        }
    }

    #endregion

    #region SystemTextJson
    /// <summary>
    /// DateTimeConverter
    /// </summary>
    public class DateTimeConverter : System.Text.Json.Serialization.JsonConverter<DateTime>
    {
        /// <summary>
        /// 时间格式化格式
        /// </summary>
        public string Format { get; private set; }

        /// <summary>
        /// 默认构造函数
        /// </summary>
        public DateTimeConverter()
        {
            Format ??= "yyyy-MM-dd HH:mm:ss";
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="format"></param>
        public DateTimeConverter(string format)
        {
            Format = format;
        }

        public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            return DateTime.Parse(reader.GetString());
        }

        public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
        {
            writer.WriteStringValue(value.ToString("yyyy-MM-dd HH:mm:ss"));
        }
    }

    /// <summary>
    /// EmptyStringConverter
    /// </summary>
    public class EmptyStringConverter : System.Text.Json.Serialization.JsonConverter<string>
    {
        public override bool HandleNull => true;

        public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
            => reader.TokenType == JsonTokenType.Null ? "" : reader.GetString();

        public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) =>
            writer.WriteStringValue(value ?? "");
    }

    public class NullableConverter<T> : System.Text.Json.Serialization.JsonConverter<T?> where T : struct
    {

        public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            if (reader.TokenType == JsonTokenType.String)
            {
                if (string.IsNullOrEmpty(reader.GetString()) || string.IsNullOrWhiteSpace(reader.GetString()))
                {
                    return null;
                }
            }
            return JsonSerializer.Deserialize<T>(ref reader, options);
        }


        public override void Write(Utf8JsonWriter writer, T? value, JsonSerializerOptions options)
        {
            JsonSerializer.Serialize(writer, value!.Value, options);
        }

    }

    #endregion
}

